package com.gitee.cui.server.server;

import com.gitee.cui.common.common.bean.User;
import com.gitee.cui.common.common.bean.msg.ProtoMsg;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelHandlerContext;
import io.netty.util.AttributeKey;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.util.UUID;

/**
 * 服务端session
 * @author cuiqingqiang
 * @version 1.0
 * @date 2021/10/28 8:44
 **/
@Slf4j
@Data
public class ServerSession {

    public static final AttributeKey<String> KEY_USER_ID = AttributeKey.valueOf("key_user_id");

    public static final AttributeKey<ServerSession> SESSION_KEY = AttributeKey.valueOf("SESSION_KEY");

    /**
     * 用户信息
     */
    private User user;

    /**
     * 通道信息
     */
    private Channel channel;

    /**
     * sessionId
     */
    private String sessionId;

    /**
     * 登录状态
     */
    private boolean login = false;

    public ServerSession (Channel channel) {
        this.channel = channel;
        this.sessionId = buildNewSessionId();
    }

    /**
     * 关闭session
     * @param ctx
     */
    public static void closeSession(ChannelHandlerContext ctx) {
        ServerSession session = ctx.channel().attr(SESSION_KEY).get();
        if (session != null && session.isValid()) {
            session.close();
            SessionMap.inst().removeSession(session.getSessionId());
        }
    }

    /**
     * 关闭session，关闭连接
     */
    private void close() {
        ChannelFuture future = channel.close();
        future.addListener(close -> {
            if (!close.isSuccess()) {
                log.error("channel close error");
            }
        });
    }

    /**
     * 判断session是否有效
     * @return session是否有效
     */
    private boolean isValid() {
        return getUser() != null;
    }

    /**
     * 使用uuid构建sessionId
     * @return sessionId
     */
    private String buildNewSessionId() {
        String uuid = UUID.randomUUID().toString();
        return uuid.replaceAll("-", "");
    }

    /**
     * 和channel实现双向绑定
     */
    public ServerSession bind() {
        log.info("ServerSession绑定会话 " + channel.remoteAddress());
        channel.attr(SESSION_KEY).set(this);
        SessionMap.inst().addSession(this);
        login = true;
        return this;
    }

    /**
     * 发送响应消息
     * @param response 响应消息
     */
    public synchronized void writeAndFlush(ProtoMsg.Message response) {
        if (channel.isWritable()) {
            channel.writeAndFlush(response);
        } else {
            log.debug("通道很忙，消息被暂存了");
            // 通道比较忙，把消息暂存到队列中，等通道空闲时，再重新发送

        }
    }
}
